#include <cstdlib>

#include "swf.h"
#include "Bits.h"
#include "Matrix.h"
using namespace swfstream;
void Matrix::print() {
	printf("matrix::HasScale:%u,", (unsigned) HasScale);
	if (HasScale) {
		//		printf("NScaleBits:%u,ScaleX:0x%X,ScaleY:0x%X\n",NScaleBits,ScaleX,ScaleY);
		printf("NScaleBits:%u,ScaleX:%f,ScaleY:%f\n", NScaleBits, ScaleX,
				ScaleY);
	}
	printf("HasRotate:%u\n", (unsigned) HasRotate);
	if (HasRotate) {
		printf("NRotateBits:%u,RotateSkew0:%f,RotateSkew1:%f\n", NScaleBits,
				ScaleX, ScaleX);
	}
	printf("NTranslateBits:%u,", (unsigned) NTranslateBits);
	printf("TranslateX:%d,", (int) TranslateX);
	printf("TranslateY:%d\n", (int) TranslateY);
}
Matrix* Matrix::from_file(FILE* f) {
	//puts("reading matrix");
	Matrix *r = new Matrix;
	Bits bits;
	r->HasScale = bits.read_u(1, f);
	if (r->HasScale == 1) {
		//		fprintf(stderr,"unfinished:has_scale\n");
		//		exit(1);
		r->NScaleBits = bits.read_u(5, f);
		//uint8 NScaleBits;///< If HasScale = 1, UB[5] Bits in each scale value field
		//		uint32 tmpx,tmpy;//16.16 fix-point
		//		tmpx=bits.read_s(r->NScaleBits,f);//notice:as float
		//		tmpy=bits.read_s(r->NScaleBits,f);//notice:as float

		//		r->ScaleX=(((int)tmpx>>16))+(float)(tmpx&0xff)/0x100;
		//		r->ScaleY=(((int)tmpy>>16))+(float)(tmpy&0xff)/0x100;
		r->ScaleX = bits.read_s(r->NScaleBits, f) / (float) 0x10000; //notice:as float
		r->ScaleY = bits.read_s(r->NScaleBits, f) / (float) 0x10000; //notice:as float
		//r->ScaleX=bits.read_u(r->NScaleBits,f);//notice:as float
		//ScaleX If HasScale = 1, FB[NScaleBits] x scale value
		//r->ScaleY=bits.read_u(r->NScaleBits,f);//notice:as float
		//ScaleY If HasScale = 1,  FB[NScaleBits] y scale value
	}
	r->HasRotate = bits.read_u(1, f);
	if (r->HasRotate == 1) {
		r->NRotateBits = bits.read_u(5, f);
		r->RotateSkew0 = bits.read_s(r->NRotateBits, f) / (float) 0x10000; //notice:as float
		r->RotateSkew1 = bits.read_s(r->NRotateBits, f) / (float) 0x10000; //notice:as float

		//fprintf(stderr,"unfinished:has_scale\n");
		//exit(1);
		//uint8 NRotateBits;///< If HasRotate = 1,  UB[5] Bits in each rotate value field
		//RotateSkew0 If HasRotate = 1,  FB[NRotateBits]First rotate and skew value
		//RotateSkew1 If HasRotate = 1,  FB[NRotateBits]Second rotate and skew value
	}
	r->NTranslateBits = bits.read_u(5, f);
	r->TranslateX = bits.read_s(r->NTranslateBits, f);
	r->TranslateY = bits.read_s(r->NTranslateBits, f);
	r->size = bits.byte_num();
	return r;
}
Matrix::Matrix() {
	ScaleX = 1;
	ScaleY = 1;
	RotateSkew0 = 0;
	RotateSkew1 = 0;
	TranslateX = 0;
	TranslateY = 0;
}
Point Matrix::trans(Point p) {
	//x' = x * ScaleX + y * RotateSkew1 + TranslateX
	//y' = x * RotateSkew0 + y * ScaleY + TranslateY 
	Point r;
	r.x = p.x * ScaleX + p.y * RotateSkew1 + TranslateX;
	r.y = p.x * RotateSkew0 + p.y * ScaleY + TranslateY;
	return r;
}
TiXmlElement* Matrix::toTiXmlElement() {
	TiXmlElement* r = new TiXmlElement("Matrix");
	//r->SetAttribute("HasRotate",this->HasRotate);
	//r->SetAttribute("HasScale",this->HasScale);
	if (HasScale) {
		r->SetAttribute("ScaleX", ScaleX);
		r->SetAttribute("ScaleY", ScaleX);
	}
	if (HasRotate) {
		r->SetAttribute("RotateSkew0", RotateSkew0);
		r->SetAttribute("RotateSkew1", RotateSkew1);
	}
	r->SetAttribute("TranslateX", TranslateX);
	r->SetAttribute("TranslateY", TranslateY);
	//this->
	return r;
}
